#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <array>
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include "data.h"

using namespace std;



/*************************************8
* The track 3->1 is the same like 1->3 
* so we do not double the same track
* but, if we search track 3->1 we 
* have to sort id's from lower to higher
* to find the path 
* but remember that the lenght will
* be decreased in that case from lenght to 0
*************************************/

ctrain::ctrain(int id):m_train_id(id),m_index_route(0),m_end_road(false){

	m_plan = new train_plan();
}

ctrain::~ctrain(){

	delete (m_plan);
}

void ctrain::add_station(station & _station){

	m_plan->push_back(_station);
}

void ctrain::init_train(){
	
    int index = m_index_route; 
	if(m_index_route < (m_plan->size() - 1)){
	  
        connection conn(m_plan->at(index),m_plan->at(++m_index_route));
		//printf("st_source:%d  st_dest:%d\n", conn.source.id, conn.destination.id);
		this->m_curr_position = m_route->get_lenght(conn);
		if(this->m_curr_position == -1){
             printf("train no:%d has no route to drive.\n",this->m_train_id);
             this->m_end_road = true;
		}
		m_current_path.first  = conn;
		m_current_path.second = this->m_curr_position;
		this->m_speed = ((conn.source.id > conn.destination.id)?-1:1);
		if(conn.source.id > conn.destination.id)
			this->m_curr_position = 0;
	}else{
		this->m_end_road = true;
	}
}

void ctrain::init_train(crouteplan & routeplan){

	//if the station.source.id > station.dest.id
	//then speed = -1
	this->m_route = &routeplan;
	init_train();
}

   /************************************************
	* The step is based on following assumpt.:
	* 1. The first station 
	*   a. Get the second station and lenght between them
	*   b. remeber to keep the order, lower number -> higher number of station
	*   c. if we have change order set the step -1
	*   d. if the current position = 0 means we reach the station_source
	*   e. otherwise station destination of route
	* 2. Each step is just decrease the number of current position
	* 3. On the station (which is on route plan) train stays 1 step
	* 4. Otherwise just continue the driving
	* 
	* the function returns the the simple structure <station_id(lower), station_id(higher), current position on track>
	* 
	**************************************************/
void ctrain::make_step(){

   /*****************************
   * if current_pos.length = 0 or max(lenght) 
   * it means we reach the station 
   * for that case we replace the train path
   * with a new one
   *****************************/
	if(!m_end_road){
		//1. set the last posiotion to current one
		this->m_last_position = this->m_curr_position;
		//2. do a one step (add speed)
		this->m_curr_position -= this->m_speed;
		//print the current position
		printf("-----train no:%d path:%d->%d pos:%d\n",this->m_train_id, this->m_current_path.first.source.id,this->m_current_path.first.destination.id, this->m_curr_position);
		//3. if current_pos = 0 or = lenght
		//reinitialize train route
		if(this->m_curr_position == 0 || this->m_curr_position == this->m_current_path.second){

			this->init_train();
			this->m_last_position = this->m_curr_position;
		}
	}else{
		printf("-----train no:%d finish route at station %d\n", this->m_train_id, this->m_current_path.first.destination.id);
	}
}

bool ctrain::is_collision(const ctrain * _train) const{

	bool result = false;
	/* collision happens when
	*  1. _train.current_pos = this.current_pos
	*  or
	*  2. _train.last_pos < this.last_pos && _train.current_pos > this.current_pos
	*  or
	*  3. _train.last_pos > this.last_pos && _train.current_pos < this.current_pos
	*
	*********************************/
    //1. Check if the connection is equal
	
	if(this->m_current_path == _train->m_current_path){

		//Now the path are same, check the current_pos
		if((this->m_curr_position == _train->m_curr_position)||
		   ((this->m_curr_position < _train->m_curr_position) && (this->m_last_position > _train->m_last_position)) ||
		   ((this->m_curr_position > _train->m_curr_position) && (this->m_last_position < _train->m_last_position))){

			   printf("--***train no:%d collided with train no:%d on route: %d-%d on position: %d\n", 
				                         this->m_train_id, _train->m_train_id, 
										 this->m_current_path.first.source.id, 
										 this->m_current_path.first.destination.id,
										 this->m_curr_position);
			   result = true;
		}
	}
	return result;
}




/********************************************************************************/
